package com.ocm.tourism.web;

import java.awt.Dimension;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.util.UriUtils;
import org.springframework.web.util.WebUtils;

import com.ocm.tourism.core.domain.Advertisement;
import com.ocm.tourism.core.domain.Business;
import com.ocm.tourism.core.domain.BusinessType;
import com.ocm.tourism.core.domain.CommonItems;
import com.ocm.tourism.core.domain.Distance;
import com.ocm.tourism.core.domain.FileInfo;
import com.ocm.tourism.core.domain.Hotel;
import com.ocm.tourism.core.domain.MapInfo;
import com.ocm.tourism.core.domain.Priority;
import com.ocm.tourism.core.domain.Room;
import com.ocm.tourism.core.domain.SaleOff;
import com.ocm.tourism.core.model.HotelCriteria;
import com.ocm.tourism.core.service.BusinessService;
import com.ocm.tourism.core.service.CataloguesService;
import com.ocm.tourism.core.service.CommonItemsService;
import com.ocm.tourism.core.service.FileInfoService;
import com.ocm.tourism.core.user.BusinessServiceClient;
import com.ocm.tourism.core.util.TourismUtil;
import com.ocm.tourism.file.MimeTypeSupport;
import com.ocm.tourism.file.SimpleImageInfo;
import com.ocm.tourism.web.util.FileInfoUtil;

@RequestMapping("/hotel")
@Controller
@SessionAttributes("sessionErrorObjects")
public class HotelController {

   private final static String SESSION_ERROROBJECTS="sessionErrorObjects"; 
   @Autowired
   CataloguesService cataloguesService;

   @Autowired
   BusinessService businessService;

   @Autowired
   BusinessServiceClient businessServiceClient;

   @Autowired
   CommonItemsService commonItemsService;

   @Autowired
   FileInfoUtil fileInfoUtil;

   @Autowired
   FileInfoService fileInfoService;

   @InitBinder
   public void initBinder(WebDataBinder binder) {
        binder.initDirectFieldAccess();
        SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
        dateFormat.setLenient(false);
        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
    }

   @RequestMapping(value = "/view")
   public String viewNew(Model uiModel, SessionStatus sessionStatus) {
      sessionStatus.setComplete();
      int sizeNo = 25;
      int firstResult = 0;
      int page = 1;
      long count = this.businessService.countSaleOffHotels();
      float nrOfPages = (float) count / sizeNo;
      uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
      if (page <= nrOfPages){
         uiModel.addAttribute("nextPage", page + 1);
      }else {
         uiModel.addAttribute("nextPage", 0);
      }
      uiModel.addAttribute("hotels", businessService.findSaleOffHotels(firstResult, sizeNo));
      uiModel.addAttribute("submenuSelected", "hotel");
      HotelCriteria hotelCriteria = new HotelCriteria();
      uiModel.addAttribute("hotelCriteria", hotelCriteria);
      return "hotel/view";
   }

   @RequestMapping(value="/view/next",produces = "text/html", method=RequestMethod.GET)
   public String listSaleOffHotels(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      long count = this.businessService.countSaleOffHotels();
       if (page != null || size != null) {
           int sizeNo = size == null ? 10 : size.intValue();
           final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
           uiModel.addAttribute("hotels", businessService.findSaleOffHotels(firstResult, sizeNo));
           float nrOfPages = (float) count / sizeNo;
           uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
           if (page < nrOfPages){
              uiModel.addAttribute("nextPage", page + 1);
           }else {
              uiModel.addAttribute("nextPage", 0);
           }
       } else {
           uiModel.addAttribute("hotels", count == 0 ? new ArrayList<Business>() : businessService.findSaleOffHotels(0, 25));
       }
       return "hotel/view/next";
   }

   @RequestMapping(value="/view/advs",produces = "text/html", method=RequestMethod.GET)
   public String listHotelAdvs(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      long count = businessService.countHotelAdvs();
      page = page == null ? 1 : page; 
      int sizeNo = size == null ? 25 : size.intValue();
      final int firstResult = (page.intValue() - 1) * sizeNo;
      uiModel.addAttribute("hotels", businessService.findHotelAdvs(firstResult, sizeNo));
      float nrOfPages = (float) count / sizeNo;
      int maxPages = (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages);
      uiModel.addAttribute("maxPages", maxPages);
      uiModel.addAttribute("nextPage", TourismUtil.getNextPage(page, maxPages));
       return "hotel/view/advs";
   }

   @RequestMapping(value = "/{id}", method=RequestMethod.GET)
   public String show(@PathVariable("id") Long id, Model uiModel, SessionStatus sessionStatus) {
      sessionStatus.setComplete();
      uiModel.addAttribute("itemId", id);
      return "hotel/show";
   }

   @RequestMapping(value = "/detail/{id}", method=RequestMethod.GET)
   public String showDetail(@PathVariable("id") Long id, Model uiModel) {
      Hotel hotel = this.businessService.findhotel(id);
      uiModel.addAttribute("hotel", hotel);
      uiModel.addAttribute("distances", hotel.getDistances());
      uiModel.addAttribute("mapInfo", hotel.getMapInfo());
      uiModel.addAttribute("submenuSelected", "hotel");
      return "hotel/detail";
   }

   @RequestMapping(value = "/{id}/update", method=RequestMethod.GET)
   public String showUpdate(@PathVariable("id") Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "info");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/update/form");
       return "hotel/show";
   }

   @RequestMapping(value = "/{id}/info", method=RequestMethod.GET)
   public String viewInfo(@PathVariable("id")Long businessId, Model uiModel) {
      Business business = businessServiceClient.findBusiness(businessId);
      uiModel.addAttribute("itemId", businessId);
      populateEditForm(uiModel, business);
      return "hotel/view/info";
   }
   
   @RequestMapping(value = "/{id}/update/form", method=RequestMethod.GET)
   public String updateInfo(@PathVariable("id")Long businessId, Model uiModel) {
      Business business = businessServiceClient.findBusiness(businessId);
      populateEditForm(uiModel, business);
      return "hotel/update/info";
   }

   @RequestMapping(value = "/{id}/room",produces = "text/html", method=RequestMethod.GET)
   public String viewRoom(@PathVariable("id")Long hotelId,@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      long countRooms = businessService.countRooms(hotelId);
      if (page != null || size != null) {
         int sizeNo = size == null ? 10 : size.intValue();
         final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
         uiModel.addAttribute("rooms", businessService.findRooms(hotelId, firstResult, sizeNo));
         float nrOfPages = (float) countRooms / sizeNo;
         uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
      } else {
         uiModel.addAttribute("rooms", countRooms == 0 ? new ArrayList<Room>() : businessService.findRooms(hotelId, 0, 25));
      }
      uiModel.addAttribute("hotelId", hotelId);
      return "hotel/room/list";
   }

   @RequestMapping(value = "/{id}/room/list", method = RequestMethod.GET)
   public String listRoomForms(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "room");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/room?page=1&size=50");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/room/create", method = RequestMethod.GET)
   public String infoCreateRoomForm(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "room");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/room/create/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/room/{roomId}/update", method = RequestMethod.GET)
   public String infoUpdateRoomForm(@PathVariable("id")Long businessId,@PathVariable("roomId")Long roomId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "room");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/room/"+roomId+"/update/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/room/create/form", method = RequestMethod.GET)
   public String createRoomForm(@PathVariable("id")Long hotelId, Model uiModel, SessionStatus sessionStatus) {
      uiModel.addAttribute("itemId", hotelId);
      Room room = new Room();
      if (uiModel.containsAttribute(SESSION_ERROROBJECTS) && uiModel.asMap().get(SESSION_ERROROBJECTS) != null){
         Model ssUIModel = (Model) uiModel.asMap().get(SESSION_ERROROBJECTS);
         uiModel.addAllAttributes(ssUIModel.asMap());
         room = (Room) uiModel.asMap().get("room");
         sessionStatus.setComplete();
      }
      populateEditRoomForm(uiModel, room);
      return "hotel/room/create";
   }

   @RequestMapping(value = "/{id}/room/{roomId}/update/form", method = RequestMethod.GET)
   public String updateRoomForm(@PathVariable("id")Long hotelId,@PathVariable("roomId")Long roomId, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      uiModel.addAttribute("itemId", hotelId);
      uiModel.addAttribute("roomId", roomId);
      Room room = this.businessService.findRoom(roomId);
      populateEditRoomForm(uiModel, room);
      return "hotel/room/update";
   }

   @RequestMapping(value="/{id}/room", method = RequestMethod.POST)
   public String addRoom(@PathVariable("id")Long hotelId, @Valid Room room,  BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      room.setId(null);
      if (bindingResult.hasErrors()) {
         uiModel.addAttribute("itemId", hotelId);
         uiModel.addAttribute("selected", "room");
         uiModel.addAttribute("selectedUrl", "/hotel/"+hotelId+"/room/create/form");
         uiModel.addAttribute(SESSION_ERROROBJECTS, uiModel);
         return "hotel/show";
      }
      uiModel.asMap().clear();
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.addRoom(room);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/room/list";
   }

   @RequestMapping(value="/{id}/room/{roomId}", method = RequestMethod.PUT)
   public String updateRoom(@PathVariable("id")Long hotelId,@PathVariable("roomId")Long roomId,@Valid Room room, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      room.setId(roomId);
      if (bindingResult.hasErrors()) {
         populateEditRoomForm(uiModel, room);
         return "hotel/room/create";
      }
      uiModel.asMap().clear();
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.updateRoom(room);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/room/list";
   }

   @RequestMapping(value="/{id}/room/{roomId}", method = RequestMethod.DELETE)
   public String updateRoom(@PathVariable("id")Long hotelId,@PathVariable("roomId")Long roomId) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.removeRoom(roomId);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/room/list";
   }

   @RequestMapping(value = "/{id}/saleoff/{saleoffId}", method = RequestMethod.GET)
   public String showSaleOff(@PathVariable("id")Long businessId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "saleoff");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/saleoff/"+saleoffId+"/show");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/saleoff/{saleoffId}/show", method = RequestMethod.GET)
   public String displaySaleOff(@PathVariable("id")Long hotelId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      uiModel.addAttribute("hotelId", hotelId);
      uiModel.addAttribute("itemId", saleoffId);
      SaleOff saleOff = this.businessService.findSaleOff(saleoffId);
      populateEditSaleOffForm(uiModel, saleOff);
      return "hotel/saleoff/show";
   }

   @RequestMapping(value = "/{id}/saleoff/list", method = RequestMethod.GET)
   public String viewSaleOffs(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "saleoff");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/saleoff?page=1&size=50");
      return "hotel/show";
   }
   
   @RequestMapping(value = "/{id}/saleoff",produces = "text/html", method=RequestMethod.GET)
   public String listSaleOffs(@PathVariable("id")Long hotelId,@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      long countSaleOffs = businessService.countSaleOffs(hotelId);
      if (page != null || size != null) {
         int sizeNo = size == null ? 10 : size.intValue();
         final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
         uiModel.addAttribute("saleoffs", businessService.findSaleOffs(hotelId, firstResult, sizeNo));
         float nrOfPages = (float) countSaleOffs / sizeNo;
         uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
      } else {
         uiModel.addAttribute("saleoffs", countSaleOffs == 0 ? new ArrayList<SaleOff>() : businessService.findSaleOffs(hotelId, 0, 25));
      }
      uiModel.addAttribute("hotelId", hotelId);
      return "hotel/saleoff/list";
   }

   @RequestMapping(value = "/{id}/saleoff/create", method = RequestMethod.GET)
   public String createSaleOff(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "saleoff");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/saleoff/create/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/saleoff/create/form", method = RequestMethod.GET)
   public String createSaleOffForm(@PathVariable("id")Long hotelId, Model uiModel, SessionStatus sessionStatus) {
      uiModel.addAttribute("itemId", hotelId);
      SaleOff saleOff = new SaleOff();
      if (uiModel.containsAttribute(SESSION_ERROROBJECTS) && uiModel.asMap().get(SESSION_ERROROBJECTS) != null){
         Model ssUIModel = (Model) uiModel.asMap().get(SESSION_ERROROBJECTS);
         uiModel.addAllAttributes(ssUIModel.asMap());
         saleOff = (SaleOff) uiModel.asMap().get("saleoff");
         sessionStatus.setComplete();
      }
      populateEditSaleOffForm(uiModel, saleOff);
      return "hotel/saleoff/create";
   }

   @RequestMapping(value="/{id}/saleoff", method = RequestMethod.POST)
   public String addSaleOff(@PathVariable("id")Long hotelId,@Valid SaleOff saleOff, BindingResult bindingResult, Model uiModel) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      saleOff.setId(null);
      if (bindingResult.hasErrors()) {
         uiModel.addAttribute(SESSION_ERROROBJECTS, uiModel);
         String result = createSaleOff(hotelId, uiModel);
         return result;
      }
      uiModel.asMap().clear();
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.addSaleOff(saleOff);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/saleoff/list";
   }

   @RequestMapping(value="/{id}/saleoff/{saleOffId}", method = RequestMethod.PUT)
   public String updateSaleOff(@PathVariable("id")Long hotelId,@PathVariable("saleOffId")Long saleOffId,@Valid SaleOff saleOff, BindingResult bindingResult, Model uiModel) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      saleOff.setId(saleOffId);
      if (bindingResult.hasErrors()) {
         uiModel.addAttribute(SESSION_ERROROBJECTS, uiModel);
         String result = createSaleOff(hotelId,uiModel);
         return result;
      }
      uiModel.asMap().clear();
      SaleOff actualSaleOff = this.businessService.findSaleOff(saleOffId);
      saleOff.setAdvertisement(actualSaleOff.getAdvertisement());
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.addSaleOff(saleOff);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/saleoff/list";
   }

   @RequestMapping(value = "/{id}/saleoff/{saleoffId}/update", method = RequestMethod.GET)
   public String updateSaleOff(@PathVariable("id")Long businessId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "saleoff");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/saleoff/"+saleoffId+"/update/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/saleoff/{saleoffId}/update/form", method = RequestMethod.GET)
   public String updatSaleOffForm(@PathVariable("id")Long hotelId,@PathVariable("saleoffId")Long saleoffId, Model uiModel, SessionStatus sessionStatus) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      uiModel.addAttribute("itemId", hotelId);
      uiModel.addAttribute("saleoffId", saleoffId);
      SaleOff saleOff = this.businessService.findSaleOff(saleoffId);
      if (uiModel.containsAttribute(SESSION_ERROROBJECTS) && uiModel.asMap().get(SESSION_ERROROBJECTS) != null){
         Model ssUIModel = (Model) uiModel.asMap().get(SESSION_ERROROBJECTS);
         uiModel.addAllAttributes(ssUIModel.asMap());
         saleOff = (SaleOff) uiModel.asMap().get("saleoff");
         sessionStatus.setComplete();
      }
      populateEditSaleOffForm(uiModel, saleOff);
      return "hotel/saleoff/update";
   }

   @RequestMapping(value="/{id}/saleoff/{saleoffId}", method = RequestMethod.DELETE)
   public String removeSaleOff(@PathVariable("id")Long hotelId,@PathVariable("saleoffId")Long saleoffId) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.removeSaleOff(saleoffId);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+hotelId+"/saleoff/list";
   }
   
   @RequestMapping(value = "/{id}/advertisement/list", method = RequestMethod.GET)
   public String listAdvertisements(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "advertisement");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/advertisement?page=1&size=50");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/advertisement",produces = "text/html", method=RequestMethod.GET)
   public String listAdvertisements(@PathVariable("id")Long businessId,@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
     listSaleOffs(businessId, page, size, uiModel);
     return "hotel/advertisement/list";
   }

   @RequestMapping(value = "/{id}/advertisement/{saleoffId}", method = RequestMethod.GET)
   public String showAdvertisement(@PathVariable("id")Long businessId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "advertisement");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/advertisement/"+saleoffId+"/show");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/advertisement/{saleoffId}/show", method = RequestMethod.GET)
   public String displayAdvertisement(@PathVariable("id")Long businessId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      displaySaleOff(businessId, saleoffId, uiModel);
      return "hotel/advertisement/show";
   }

   @RequestMapping(value = "/{id}/advertisement/{saleoffId}/update", method = RequestMethod.GET)
   public String updateAdvertisement(@PathVariable("id")Long businessId,@PathVariable("saleoffId")Long saleoffId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "advertisement");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/advertisement/"+saleoffId+"/update/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/advertisement/{saleoffId}/update/form", method = RequestMethod.GET)
   public String updateAdvertisementForm(@PathVariable("id")Long hotelId,@PathVariable("saleoffId")Long saleoffId, Model uiModel, SessionStatus sessionStatus) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      uiModel.addAttribute("itemId", hotelId);
      uiModel.addAttribute("saleoffId", saleoffId);
      SaleOff saleOff = this.businessService.findSaleOff(saleoffId);
      Advertisement advertisement = saleOff.getAdvertisement();
      advertisement = advertisement == null ? new Advertisement() : advertisement;
      if (uiModel.containsAttribute(SESSION_ERROROBJECTS) && uiModel.asMap().get(SESSION_ERROROBJECTS) != null){
         Model ssUIModel = (Model) uiModel.asMap().get(SESSION_ERROROBJECTS);
         uiModel.addAllAttributes(ssUIModel.asMap());
         advertisement = (Advertisement) uiModel.asMap().get("advertisement");
         sessionStatus.setComplete();
      }
      uiModel.addAttribute("advertisement", advertisement);
      uiModel.addAttribute("prioritise", Arrays.asList(Priority.values()));
      populateEditSaleOffForm(uiModel, saleOff);
      return "hotel/advertisement/update";
   }
   
   @RequestMapping(value="{hotelId}/advertisement/{saleoffId}", method = RequestMethod.PUT)
   public String updateAdvs(@PathVariable("hotelId")Long hotelId, @PathVariable("saleoffId")Long saleoffId,@Valid Advertisement advertisement, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, SessionStatus sessionStatus) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      if (bindingResult.hasErrors()) {
         uiModel.addAttribute(SESSION_ERROROBJECTS, uiModel);
         return updateAdvertisement(hotelId, saleoffId, uiModel);
      }
      
      uiModel.asMap().clear();
      sessionStatus.setComplete();
      SaleOff saleoff = this.businessService.findSaleOff(saleoffId);
      advertisement.setModifiedDate(new Date(System.currentTimeMillis()));
      saleoff.setAdvertisement(advertisement);
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.updateSaleOff(saleoff);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+encodeUrlPathSegment(hotelId.toString(), httpServletRequest)+"/advertisement/list";
   }

   @RequestMapping(value="{hotelId}/advertisement/{saleoffId}", method = RequestMethod.DELETE)
   public String deleteAdvs(@PathVariable("hotelId")Long hotelId, @PathVariable("saleoffId")Long saleoffId,Model uiModel,HttpServletRequest httpServletRequest) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      SaleOff saleoff = this.businessService.findSaleOff(saleoffId);
      saleoff.setAdvertisement(null);
      Hotel hotel = this.businessService.findhotel(hotelId);
      hotel.updateSaleOff(saleoff);
      this.businessService.saveBusiness(hotel);
      return "redirect:/hotel/"+encodeUrlPathSegment(hotelId.toString(), httpServletRequest)+"/advertisement/list";
   }

   @RequestMapping(value = "/{id}/distance/update", method = RequestMethod.GET)
   public String infoUpdateDistances(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "distance");
      uiModel.addAttribute("selectedUrl", "/distance/"+businessId+"/update/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/distance",produces = "text/html", method=RequestMethod.GET)
   public String viewDistances(@PathVariable("id")Long hotelId, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
      List<Distance> distances = businessService.findDistances(hotelId);
      uiModel.addAttribute("distances", distances);
      uiModel.addAttribute("businessId", hotelId);
      uiModel.addAttribute("businessType", "hotel");
      return "distance/show";
   }

   @RequestMapping(value = "/{id}/distance/list",produces = "text/html", method=RequestMethod.GET)
   public String viewDistancesList(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "distance");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/distance");
      return "hotel/show";
   }
   
   @RequestMapping(value = "/{id}/map", produces = "text/html", method = RequestMethod.GET)
   public String viewMapInfos(@PathVariable("id") Long hotelId, Model uiModel) {
      this.businessServiceClient.validatedAcceptBusiness(hotelId);
       MapInfo mapInfo = businessService.findMap(hotelId);
       if (mapInfo != null){
          uiModel.addAttribute("latitude", mapInfo.getLatitude());
          uiModel.addAttribute("longitude", mapInfo.getLongitude());
       }else {
          uiModel.addAttribute("latitude", 0);
          uiModel.addAttribute("longitude", 0);
       }
       uiModel.addAttribute("hotelId", hotelId);
       return "hotel/map/show";
   }

   @RequestMapping(value = "/{id}/map/update", method = RequestMethod.GET)
   public String infoUpdateMap(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "map");
      uiModel.addAttribute("selectedUrl", "/map/"+businessId+"/update/form");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/map/show", method = RequestMethod.GET)
   public String showMap(@PathVariable("id")Long businessId, Model uiModel) {
      uiModel.addAttribute("itemId", businessId);
      uiModel.addAttribute("selected", "map");
      uiModel.addAttribute("selectedUrl", "/hotel/"+businessId+"/map");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/files",produces = "text/html", method=RequestMethod.GET)
   public String viewFiles(@PathVariable("id")Long hotelId, Model uiModel) {
      uiModel.addAttribute("itemId", hotelId);
      uiModel.addAttribute("selected", "file");
      uiModel.addAttribute("selectedUrl", "/fileInfo/business/"+hotelId+"/hotel");
      return "hotel/show";
   }

   @RequestMapping(value = "/{id}/file/create",produces = "text/html", method=RequestMethod.GET)
   public String viewCreate(@PathVariable("id")Long hotelId, Model uiModel) {
      uiModel.addAttribute("itemId", hotelId);
      uiModel.addAttribute("selected", "file");
      uiModel.addAttribute("selectedUrl", "/fileInfo/business/"+hotelId+"/hotel/create");
      return "hotel/show";
   }

   @RequestMapping(value = "/create", method = RequestMethod.GET)
   public String createForm(Model uiModel) {
      Business business = new Business();
      business.setBusinessType(BusinessType.HOTEL);
      populateEditForm(uiModel, business);
      return "hotel/create";
   }

   @RequestMapping(value="/search",method = RequestMethod.GET)
   public String viewSearch(Model uiModel){
      HotelCriteria hotelCriteria = new HotelCriteria();
      uiModel.addAttribute("hotelCriteria", hotelCriteria);
      return "hotel/search";
   }

   @RequestMapping(value="/search/advantage",method = RequestMethod.POST)
   public String searchAdvantage(HotelCriteria hotelCriteria, Model uiModel){
      List<Hotel> hotels = this.businessService.findHotels(hotelCriteria.fill(), 0, 25);
      uiModel.addAttribute("hotels", hotels);
      return "hotel/search/list";
   }

   @RequestMapping(value="/search",method = RequestMethod.POST)
   public String search(Hotel hotel, Model uiModel){
      List<Hotel> hotels = this.businessService.findHotels(hotel.getName(), hotel.getAddress(), hotel.getHomephone(), hotel.getMobilephone());
      uiModel.addAttribute("hotels", hotels);
      return "hotel/searchResult";
   }

   @RequestMapping(method = RequestMethod.POST)
   public String create(@Valid Hotel business, @RequestParam("fileData")CommonsMultipartFile commonsMultipartFile, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
      validate(commonsMultipartFile, uiModel, bindingResult);
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, business);
         return "hotel/create";
      }
      if (commonsMultipartFile.getSize() > 0){
         String uploadDir = httpServletRequest.getSession().getServletContext().getInitParameter("uploadDir");
         String folderPath = fileInfoUtil.createContainer(uploadDir);
         FileInfo fileInfo = fileInfoUtil.writeFile(commonsMultipartFile, uploadDir, folderPath);
         business.setAvatar(fileInfo);
      }
      uiModel.asMap().clear();
      this.businessService.saveBusiness(business);
      return "redirect:/hotel?page=1&size=50";
   }

   @RequestMapping(value="/update", method = RequestMethod.POST)
   public String update(@Valid Hotel business, @RequestParam("fileData")CommonsMultipartFile commonsMultipartFile, BindingResult bindingResult, Model uiModel, HttpServletRequest httpServletRequest) throws Exception {
      this.businessServiceClient.validatedAcceptBusiness(business.getId());
      validate(commonsMultipartFile, uiModel, bindingResult);
      if (bindingResult.hasErrors()) {
         populateEditForm(uiModel, business);
         return "hotel/create";
      }
      Business actual = this.businessService.findBusiness(business.getId());
      if (commonsMultipartFile.getSize() > 0){
         String uploadDir = httpServletRequest.getSession().getServletContext().getInitParameter("uploadDir");
         String folderPath = fileInfoUtil.createContainer(uploadDir);
         FileInfo fileInfo = fileInfoUtil.writeFile(commonsMultipartFile, uploadDir, folderPath);
         business.setAvatar(fileInfo);
      }else{
         business.setAvatar(actual.getAvatar());
      }
      uiModel.asMap().clear();
      business.setParticipant(actual.getParticipant());
      businessService.saveBusiness(business);
      return "redirect:/businesses/" + encodeUrlPathSegment(business.getId().toString(), httpServletRequest);
   }

   @RequestMapping(produces = "text/html", method=RequestMethod.GET)
   public String list(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      long count = businessServiceClient.countHotels();
       if (page != null || size != null) {
           int sizeNo = size == null ? 10 : size.intValue();
           final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
           uiModel.addAttribute("businesses", businessServiceClient.findHotels(firstResult, sizeNo));
           float nrOfPages = (float) count / sizeNo;
           uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
       } else {
           uiModel.addAttribute("businesses", count == 0 ? new ArrayList<Business>() : businessServiceClient.findHotels(0, 25));
       }
       return "hotel/list";
   }

   @RequestMapping(value = "/viewest", produces = "text/html")
   public String showHotelViewest(@RequestParam(value = "page", required = false) Integer page, @RequestParam(value = "size", required = false) Integer size, Model uiModel) {
      long count = businessService.countHotelViewest();
      if (page != null || size != null) {
          int sizeNo = size == null ? 10 : size.intValue();
          final int firstResult = page == null ? 0 : (page.intValue() - 1) * sizeNo;
          uiModel.addAttribute("hotelViewests", businessService.findHotelViewest(firstResult, sizeNo));
          float nrOfPages = (float) count / sizeNo;
          uiModel.addAttribute("maxPages", (int) ((nrOfPages > (int) nrOfPages || nrOfPages == 0.0) ? nrOfPages + 1 : nrOfPages));
      } else {
          List<Business> businesses =  count == 0 ? new ArrayList<Business>() : businessService.findHotelViewest(0, 25);
          uiModel.addAttribute("hotelViewests", businesses);
      }
       return "hotel/viewest";
   }

   void populateEditForm(Model uiModel, Business business) {
      uiModel.addAttribute("business", business);
      List<CommonItems> countries = commonItemsService.findAllCountrys();
      countries.add(0, new CommonItems());
      uiModel.addAttribute("countries", countries);
      uiModel.addAttribute("cities", commonItemsService.findAllCitys());
   }

   void populateEditRoomForm(Model uiModel, Room room) {
      uiModel.addAttribute("room", room);
      List<CommonItems> concurrencies = commonItemsService.findAllConcurrencies();
      uiModel.addAttribute("concurrencies", concurrencies);
   }

   void populateEditSaleOffForm(Model uiModel, SaleOff saleOff) {
      uiModel.addAttribute("saleoff", saleOff == null ? new SaleOff() : saleOff);
   }

   void populateEditAdvertisementForm(Model uiModel, Advertisement advertisement) {
      uiModel.addAttribute("advertisement", advertisement);
      uiModel.addAttribute("prioritise", Arrays.asList(Priority.values()));
   }

   void validate(CommonsMultipartFile commonsMultipartFile,Model uiModel, Errors errors) throws IOException{
      if (commonsMultipartFile.getSize() > 0){
         InputStream inputStream = commonsMultipartFile.getInputStream();
         if (!MimeTypeSupport.supportMineType(commonsMultipartFile.getContentType())){
            errors.reject("error_fileData_contenttype");
         }
         if (commonsMultipartFile.getSize() > FileInfoUtil.DEFAULT_BUFFER_SIZE){
            errors.reject("error_fileData_large");
         }
         if (!errors.hasFieldErrors("fileData")){
            Dimension dimension = SimpleImageInfo.processStream(inputStream);
            if (dimension.getWidth() < 200){
               errors.reject("error_fileData_limit_width");
            }
         }
      }
   }
   
   String encodeUrlPathSegment(String pathSegment, HttpServletRequest httpServletRequest) {
      String enc = httpServletRequest.getCharacterEncoding();
      if (enc == null) {
          enc = WebUtils.DEFAULT_CHARACTER_ENCODING;
      }
      try {
          pathSegment = UriUtils.encodePathSegment(pathSegment, enc);
      } catch (UnsupportedEncodingException uee) {}
      return pathSegment;
  }
   
   @RequestMapping(value = "/{businessId}/file/{fileId}", method=RequestMethod.DELETE)
   public String deleteFile(@PathVariable("businessId") long businessId,@PathVariable("fileId")String fileId,Model uiModel) {
      this.fileInfoService.deleteFile(businessId, fileId);
      return "redirect:/hotel/"+businessId+"/files";
   }
}
